1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26 package sun.font;
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45 public final class CompositeGlyphMapper extends CharToGlyphMapper {
46
47 public static final int SLOTMASK = 0xff000000;
48 public static final int GLYPHMASK = 0x00ffffff;
49
50 public static final int NBLOCKS = 216;
51 public static final int BLOCKSZ = 256;
52 public static final int MAXUNICODE = NBLOCKS*BLOCKSZ;
53
54
55 CompositeFont font;
56 CharToGlyphMapper slotMappers[];
57 int[][] glyphMaps;
58 private boolean hasExcludes;
59
60 public CompositeGlyphMapper(CompositeFont compFont) {
61 font = compFont;
62 initMapper();
63
64
65
66 hasExcludes = compFont.exclusionRanges != null &&
67 compFont.maxIndices != null;
68 }
69
70 public final int compositeGlyphCode(int slot, int glyphCode) {
71 return (slot << 24 | (glyphCode & GLYPHMASK));
72 }
73
74 private final void initMapper() {
75 if (missingGlyph == CharToGlyphMapper.UNINITIALIZED_GLYPH) {
76 if (glyphMaps == null) {
77 glyphMaps = new int[NBLOCKS][];
78 }
79 slotMappers = new CharToGlyphMapper[font.numSlots];
80
81 missingGlyph = font.getSlotFont(0).getMissingGlyphCode();
82 missingGlyph = compositeGlyphCode(0, missingGlyph);
83 }
84 }
85
86 private int getCachedGlyphCode(int unicode) {
87 if (unicode >= MAXUNICODE) {
88 return UNINITIALIZED_GLYPH;
89 }
90 int[] gmap;
91 if ((gmap = glyphMaps[unicode >> 8]) == null) {
92 return UNINITIALIZED_GLYPH;
93 }
94 return gmap[unicode & 0xff];
95 }
96
97 private void setCachedGlyphCode(int unicode, int glyphCode) {
98 if (unicode >= MAXUNICODE) {
99 return;
100 }
101 int index0 = unicode >> 8;
102 if (glyphMaps[index0] == null) {
103 glyphMaps[index0] = new int[BLOCKSZ];
104 for (int i=0;i<BLOCKSZ;i++) {
105 glyphMaps[index0][i] = UNINITIALIZED_GLYPH;
106 }
107 }
108 glyphMaps[index0][unicode & 0xff] = glyphCode;
109 }
110
111 private final CharToGlyphMapper getSlotMapper(int slot) {
112 CharToGlyphMapper mapper = slotMappers[slot];
113 if (mapper == null) {
114 mapper = font.getSlotFont(slot).getMapper();
115 slotMappers[slot] = mapper;
116 }
117 return mapper;
118 }
119
120 private final int convertToGlyph(int unicode) {
121
122 for (int slot = 0; slot < font.numSlots; slot++) {
123 if (!hasExcludes || !font.isExcludedChar(slot, unicode)) {
124 CharToGlyphMapper mapper = getSlotMapper(slot);
125 int glyphCode = mapper.charToGlyph(unicode);
126 if (glyphCode != mapper.getMissingGlyphCode()) {
127 glyphCode = compositeGlyphCode(slot, glyphCode);
128 setCachedGlyphCode(unicode, glyphCode);
129 return glyphCode;
130 }
131 }
132 }
133 return missingGlyph;
134 }
135
136 public int getNumGlyphs() {
137 int numGlyphs = 0;
138
139
140
141
142
143
144
145
146
147 for (int slot=0; slot<1 ; slot++) {
148 CharToGlyphMapper mapper = slotMappers[slot];
149 if (mapper == null) {
150 mapper = font.getSlotFont(slot).getMapper();
151 slotMappers[slot] = mapper;
152 }
153 numGlyphs += mapper.getNumGlyphs();
154 }
155 return numGlyphs;
156 }
157
158 public int charToGlyph(int unicode) {
159
160 int glyphCode = getCachedGlyphCode(unicode);
161 if (glyphCode == UNINITIALIZED_GLYPH) {
162 glyphCode = convertToGlyph(unicode);
163 }
164 return glyphCode;
165 }
166
167 public int charToGlyph(int unicode, int prefSlot) {
168 if (prefSlot >= 0) {
169 CharToGlyphMapper mapper = getSlotMapper(prefSlot);
170 int glyphCode = mapper.charToGlyph(unicode);
171 if (glyphCode != mapper.getMissingGlyphCode()) {
172 return compositeGlyphCode(prefSlot, glyphCode);
173 }
174 }
175 return charToGlyph(unicode);
176 }
177
178 public int charToGlyph(char unicode) {
179
180 int glyphCode = getCachedGlyphCode(unicode);
181 if (glyphCode == UNINITIALIZED_GLYPH) {
182 glyphCode = convertToGlyph(unicode);
183 }
184 return glyphCode;
185 }
186
187
188
189
190
191
192 public boolean charsToGlyphsNS(int count, char[] unicodes, int[] glyphs) {
193
194 for (int i=0; i<count; i++) {
195 int code = unicodes[i];
196
197 if (code >= HI_SURROGATE_START &&
198 code <= HI_SURROGATE_END && i < count - 1) {
199 char low = unicodes[i + 1];
200
201 if (low >= LO_SURROGATE_START &&
202 low <= LO_SURROGATE_END) {
203 code = (code - HI_SURROGATE_START) *
204 0x400 + low - LO_SURROGATE_START + 0x10000;
205 glyphs[i + 1] = INVISIBLE_GLYPH_ID;
206 }
207 }
208
209 int gc = glyphs[i] = getCachedGlyphCode(code);
210 if (gc == UNINITIALIZED_GLYPH) {
211 glyphs[i] = convertToGlyph(code);
212 }
213
214 if (code < FontUtilities.MIN_LAYOUT_CHARCODE) {
215 continue;
216 }
217 else if (FontUtilities.isComplexCharCode(code)) {
218 return true;
219 }
220 else if (code >= 0x10000) {
221 i += 1;
222 continue;
223 }
224 }
225
226 return false;
227 }
228
229
230
231
232 public void charsToGlyphs(int count, char[] unicodes, int[] glyphs) {
233 for (int i=0; i<count; i++) {
234 int code = unicodes[i];
235
236 if (code >= HI_SURROGATE_START &&
237 code <= HI_SURROGATE_END && i < count - 1) {
238 char low = unicodes[i + 1];
239
240 if (low >= LO_SURROGATE_START &&
241 low <= LO_SURROGATE_END) {
242 code = (code - HI_SURROGATE_START) *
243 0x400 + low - LO_SURROGATE_START + 0x10000;
244
245 int gc = glyphs[i] = getCachedGlyphCode(code);
246 if (gc == UNINITIALIZED_GLYPH) {
247 glyphs[i] = convertToGlyph(code);
248 }
249 i += 1;
250 glyphs[i] = INVISIBLE_GLYPH_ID;
251 continue;
252 }
253 }
254
255 int gc = glyphs[i] = getCachedGlyphCode(code);
256 if (gc == UNINITIALIZED_GLYPH) {
257 glyphs[i] = convertToGlyph(code);
258 }
259 }
260 }
261
262 public void charsToGlyphs(int count, int[] unicodes, int[] glyphs) {
263 for (int i=0; i<count; i++) {
264 int code = unicodes[i];
265
266 glyphs[i] = getCachedGlyphCode(code);
267 if (glyphs[i] == UNINITIALIZED_GLYPH) {
268 glyphs[i] = convertToGlyph(code);
269 }
270 }
271 }
272
273 }